好久没更新Blog了,翻出过往的笔记,决定补充下 Java 部分的文章,鉴于目前的数量还不是很多,还是继续补充基础知识吧。
今天记录一下Java 中的 继承 和 组合,即 Inheritance VS Composition 。
继承
继承是一种子类是父类的关系,即所谓的 is-a 关系,它描述,子类是一种父类。
先上个代码:
class A {
public void funcX() {
System.out.println("This is funcX of Class A");
}
public void funcY() {
funcX();
System.out.println("This is funcY of Class A");
}
}
class B extends A {
public void funcX() {
System.out.println("This is funcX of Class B");
}
public void funcY() {
funcX();
super.funcY();
}
}
子类继承父类,子类具有父类完全的能力,能调用父类的方法,能重写方法,这里的重写方法,有另外一个概念,就是扩充父类方法,比如子类中的 super.funcY(), 这句其实是调用父类的方法,也就是说,子类有某种能力是基于父类的能力,并且,将父类的能力扩充。 所以,从这点上来讲,如果重写一个方法,和父类的方法完全不相干的,那么,从设计理念上看,就不是很合适。
因此,出现了组合
组合
interface IA {
public void funcX();
}
class AImpl implements IA {
private String whoAmI;
public AImpl(String whoAmI) {
this.whoAmI = whoAmI;
}
public void funcX() {
System.out.println("This is funcX of " + whoAmI);
}
}
class Abc {
}
class Def extends Abc implement IA {
private IA ia;
public Def(IA ia) {
this.ia = ia;
}
public void funcX() {
ia.funcX();
}
}
class Sample {
public static void main(String[] args) {
Def sample = new Def(new AImpl("Jacky"));
Def sample2 = new Def(new AImpl("Spider Man"));
}
}
从这段代码看,AI 接口抽象了某种能力,AImpl 实现了这种能力,并以参数形式区别,所以不管 父类 Abc 还是 子类 Def, 使用不同参数,达到了不同效果,也不影响继承关系,比如子类父类都有某个方法,子类重写了,里面的某个功能都是需要用到了,而且有点区别,这个时候就可以用接口。
那么这种组合的接口的好处是什么呢? 可能不够简单,画个类图,篇幅也多,为何如此呢?
这要从 Java 的设计理念来看,Java 属于学院派,重点是要把事情说清楚,并且在某一段时间内,达到很好的可扩展,只增加,不修改。所以,设计还是比较讲究的。